package org.example.dyscript.generator;

import org.example.dyscript.compiler.JavaStringCompiler;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class JavaClassGenerator {

  private final static JavaStringCompiler compiler = new JavaStringCompiler();

  private final static String newline = "\n";
  private final static String space = " ";
  private final static String semicolon = ";";
  private final static String importStr = "import";

  public static Class<?> generator(String fullClassName, Map<String, FullyQualifiedJavaType> ruleParametersType,
                                   String methodContent) throws IOException, ClassNotFoundException {
    // 生成源码
    String classSourceCode = generatorClassSourceCode(fullClassName, ruleParametersType, methodContent);

    FullyQualifiedJavaType fullyQualifiedJavaType = new FullyQualifiedJavaType(fullClassName);

    String fileName = fullyQualifiedJavaType.getShortName() + ".java";
    Map<String, byte[]> compileResult = compiler.compile(fileName, classSourceCode);
    return compiler.loadClass(fullClassName, compileResult);
  }

  public static String generatorClassSourceCode(String fullClassName,
                                                Map<String, FullyQualifiedJavaType> ruleParametersTypeMap,
                                                String expression) {
    FullyQualifiedJavaType fullyQualifiedJavaType = new FullyQualifiedJavaType(fullClassName);

    StringBuilder classSourceCode = new StringBuilder();

    // package 部分
    classSourceCode
        .append("package ")
        .append(fullyQualifiedJavaType.getPackageName())
        .append(semicolon).append(newline);
    classSourceCode.append(newline);

    // import 部分
    List<String> imports = new ArrayList<>();
    ruleParametersTypeMap.values().forEach(it -> imports.addAll(it.getImportList()));
    imports.add("org.example.dyscript.generator.EvaluateRule");
    imports.add("java.util.Map");
    for (String anImport : imports) {
      classSourceCode.append(importStr).append(space).append(anImport).append(semicolon).append(newline);
    }
    classSourceCode.append(newline);

    // class 头部分
    classSourceCode.append("public class ").append(fullyQualifiedJavaType.getShortName())
        .append(" implements EvaluateRule {\n");

    // method 部分
    classSourceCode.append("\tpublic boolean evaluate(Map<String, Object> parameters) {").append(newline);

    for (Entry<String, FullyQualifiedJavaType> stringFullyQualifiedJavaTypeEntry : ruleParametersTypeMap.entrySet()) {
      String parameterName = stringFullyQualifiedJavaTypeEntry.getKey();
      FullyQualifiedJavaType parameterType = stringFullyQualifiedJavaTypeEntry.getValue();

      classSourceCode.append("\t\t")
          .append(parameterType.getShortName())
          .append(space).append(parameterName).append(" = ")
          .append("(").append(parameterType.getShortName()).append(")")
          .append("parameters.get(\"").append(parameterName).append("\");")
          .append(newline);
    }
    classSourceCode.append(newline);

    classSourceCode.append("\t\treturn ").append(expression).append(";").append(newline);

    // close method
    classSourceCode.append("\t}").append(newline);
    // close class
    classSourceCode.append("}").append(newline);
    return classSourceCode.toString();
  }
}
